home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / 3d.exe / L1.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-22  |  7.1 KB  |  162 lines

  1. /* 3D animation program to view a cube as it rotates in
  2.    mode X. The viewpoint is fixed at the origin (0,0,0) of world
  3.    space, looking in the direction of increasingly negative Z. A
  4.    right-handed coordinate system is used throughout.
  5.    All C code tested with Borland C++ 2.0 in C compilation mode */
  6. #include <conio.h>
  7. #include <dos.h>
  8. #include <math.h>
  9. #include "polygon.h"
  10.  
  11. #define ROTATION  (M_PI / 30.0)  /* rotate by 6 degrees at a time */
  12.  
  13. /* Base offset of page to which to draw */
  14. unsigned int CurrentPageBase = 0;
  15. /* Clip rectangle; clips to the screen */
  16. int ClipMinX=0, ClipMinY=0;
  17. int ClipMaxX=SCREEN_WIDTH, ClipMaxY=SCREEN_HEIGHT;
  18. /* Rectangle specifying extent to be erased in each page */
  19. struct Rect EraseRect[2] = { {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT},
  20.    {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT} };
  21. static unsigned int PageStartOffsets[2] =
  22.    {PAGE0_START_OFFSET,PAGE1_START_OFFSET};
  23. int DisplayedPage, NonDisplayedPage;
  24. /* Transformation from cube's object space to world space. Initially
  25.    set up to perform no rotation and to move the cube into world
  26.    space -100 units away from the origin down the Z axis. Given the
  27.    viewing point, -100 down the Z axis means 100 units away in the
  28.    direction of view. The program dynamically changes both the
  29.    translation and the rotation. */
  30. static double CubeWorldXform[4][4] = {
  31.    {1.0, 0.0, 0.0, 0.0},
  32.    {0.0, 1.0, 0.0, 0.0},
  33.    {0.0, 0.0, 1.0, -100.0},
  34.    {0.0, 0.0, 0.0, 1.0} };
  35. /* Transformation from world space into view space. Because in this
  36.    application the view point is fixed at the origin of world space,
  37.    looking down the Z axis in the direction of increasing Z, view space is
  38.    identical to world space, and this is the identity matrix */
  39. static double WorldViewXform[4][4] = {
  40.    {1.0, 0.0, 0.0, 0.0},
  41.    {0.0, 1.0, 0.0, 0.0},
  42.    {0.0, 0.0, 1.0, 0.0},
  43.    {0.0, 0.0, 0.0, 1.0}
  44. };
  45. /* All vertices in the cube */
  46. static struct Point3 CubeVerts[] = {
  47.    {15,15,15,1},{15,15,-15,1},{15,-15,15,1},{15,-15,-15,1},
  48.    {-15,15,15,1},{-15,15,-15,1},{-15,-15,15,1},{-15,-15,-15,1}};
  49. /* Vertices after transformation */
  50. static struct Point3
  51.       XformedCubeVerts[sizeof(CubeVerts)/sizeof(struct Point3)];
  52. /* Vertices after projection */
  53. static struct Point3
  54.       ProjectedCubeVerts[sizeof(CubeVerts)/sizeof(struct Point3)];
  55. /* Vertices in screen coordinates */
  56. static struct Point
  57.       ScreenCubeVerts[sizeof(CubeVerts)/sizeof(struct Point3)];
  58. /* Vertex indices for individual faces */   
  59. static int Face1[] = {1,3,2,0};
  60. static int Face2[] = {5,7,3,1};
  61. static int Face3[] = {4,5,1,0};
  62. static int Face4[] = {3,7,6,2};
  63. static int Face5[] = {5,4,6,7};
  64. static int Face6[] = {0,2,6,4};
  65. /* List of cube faces */
  66. static struct Face CubeFaces[] = {{Face1,4,15},{Face2,4,14},
  67.    {Face3,4,12},{Face4,4,11},{Face5,4,10},{Face6,4,9}};
  68. /* Master description for cube */
  69. static struct Object Cube = {sizeof(CubeVerts)/sizeof(struct Point3),
  70.    CubeVerts, XformedCubeVerts, ProjectedCubeVerts, ScreenCubeVerts,
  71.    sizeof(CubeFaces)/sizeof(struct Face), CubeFaces};
  72.  
  73. void main() {
  74.    int Done = 0, RecalcXform = 1;
  75.    double WorkingXform[4][4];
  76.    union REGS regset;
  77.  
  78.    /* Set up the initial transformation */
  79.    Set320x240Mode(); /* set the screen to mode X */
  80.    ShowPage(PageStartOffsets[DisplayedPage = 0]);
  81.    /* Keep transforming the cube, drawing it to the undisplayed page,
  82.       and flipping the page to show it */
  83.    do {
  84.       /* Regenerate the object->view transformation and
  85.          retransform/project if necessary */
  86.       if (RecalcXform) {
  87.          ConcatXforms(WorldViewXform, CubeWorldXform, WorkingXform);
  88.          /* Transform and project all the vertices in the cube */
  89.          XformAndProjectPoints(WorkingXform, &Cube);
  90.          RecalcXform = 0;
  91.       }
  92.       CurrentPageBase =    /* select other page for drawing to */
  93.             PageStartOffsets[NonDisplayedPage = DisplayedPage ^ 1];
  94.       /* Clear the portion of the non-displayed page that was drawn
  95.          to last time, then reset the erase extent */
  96.       FillRectangleX(EraseRect[NonDisplayedPage].Left,
  97.             EraseRect[NonDisplayedPage].Top,
  98.             EraseRect[NonDisplayedPage].Right,
  99.             EraseRect[NonDisplayedPage].Bottom, CurrentPageBase, 0);
  100.       EraseRect[NonDisplayedPage].Left =
  101.             EraseRect[NonDisplayedPage].Top = 0x7FFF;
  102.       EraseRect[NonDisplayedPage].Right =
  103.             EraseRect[NonDisplayedPage].Bottom = 0;
  104.       /* Draw all visible faces of the cube */
  105.       DrawVisibleFaces(&Cube);
  106.       /* Flip to display the page into which we just drew */
  107.       ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
  108.       while (kbhit()) {
  109.          switch (getch()) {
  110.             case 0x1B:     /* Esc to exit */
  111.                Done = 1; break;
  112.             case 'A': case 'a':      /* away (-Z) */
  113.                CubeWorldXform[2][3] -= 3.0; RecalcXform = 1; break;
  114.             case 'T':      /* towards (+Z). Don't allow to get too */
  115.             case 't':      /* close, so Z clipping isn't needed */
  116.                if (CubeWorldXform[2][3] < -40.0) {
  117.                      CubeWorldXform[2][3] += 3.0;
  118.                      RecalcXform = 1;
  119.                }
  120.                break;
  121.             case '4':         /* rotate clockwise around Y */
  122.                AppendRotationY(CubeWorldXform, -ROTATION);
  123.                RecalcXform=1; break;
  124.             case '6':         /* rotate counterclockwise around Y */
  125.                AppendRotationY(CubeWorldXform, ROTATION);
  126.                RecalcXform=1; break;
  127.             case '8':         /* rotate clockwise around X */
  128.                AppendRotationX(CubeWorldXform, -ROTATION);
  129.                RecalcXform=1; break;
  130.             case '2':         /* rotate counterclockwise around X */
  131.                AppendRotationX(CubeWorldXform, ROTATION);
  132.                RecalcXform=1; break;
  133.             case 0:     /* extended code */
  134.                switch (getch()) {
  135.                   case 0x3B:  /* rotate counterclockwise around Z */
  136.                      AppendRotationZ(CubeWorldXform, ROTATION);
  137.                      RecalcXform=1; break;
  138.                   case 0x3C:  /* rotate clockwise around Z */
  139.                      AppendRotationZ(CubeWorldXform, -ROTATION);
  140.                      RecalcXform=1; break;
  141.                   case 0x4B:  /* left (-X) */
  142.                     CubeWorldXform[0][3] -= 3.0; RecalcXform=1; break;
  143.                   case 0x4D:  /* right (+X) */
  144.                     CubeWorldXform[0][3] += 3.0; RecalcXform=1; break;
  145.                   case 0x48:  /* up (+Y) */
  146.                     CubeWorldXform[1][3] += 3.0; RecalcXform=1; break;
  147.                   case 0x50:  /* down (-Y) */
  148.                     CubeWorldXform[1][3] -= 3.0; RecalcXform=1; break;
  149.                   default:
  150.                     break;
  151.                }
  152.                break;
  153.             default:       /* any other key to pause */
  154.                getch(); break;
  155.          }
  156.       }
  157.    } while (!Done);
  158.    /* Return to text mode and exit */
  159.    regset.x.ax = 0x0003;   /* AL = 3 selects 80x25 text mode */
  160.    int86(0x10, ®set, ®set);
  161. }
  162.